package query

import (
	"fmt"
	"path/filepath"
	"strings"

	"github.com/glennliao/apijson-go/consts"
	"github.com/glennliao/apijson-go/model"
	"github.com/glennliao/apijson-go/util"
)

type H函数节点 struct {
	J节点 *J节点
}

func X新建函数节点(n *J节点) *H函数节点 {
	return &H函数节点{J节点: n}
}

func (h *H函数节点) J解析() {
	// 保持原功能不变
}

func (h *H函数节点) H获取数据() {
	// 保持原功能不变

}

func (h *H函数节点) C处理结果() {
	当前节点 := h.J节点
	查询配置 := 当前节点.C查询上下文.C查询配置

	函数名, 参数键列表 := util.J解析函数字符串(当前节点.J简单请求值)

	函数 := 查询配置.H获取函数(函数名)

	if 函数 == nil {
		当前节点.C错误 = consts.X新建请求验证错误("functions not exists: " + 函数名)
		return
	}

	// todo batch support

	参数 := model.Map{}

	for i, 参数定义 := range 函数.C参数列表 {
		参数名 := 参数键列表[i]
		if strings.HasPrefix(参数名, "/") { // 这里/开头是相对同级
			目录 := filepath.Dir(当前节点.L路径)
			if 目录 == "." {
				目录 = ""
				参数名 = 参数名[1:]
			}
			参数名 = 目录 + 参数名
		}
		引用路径, 参数名 := util.X解析引用列(参数名)
		if 引用路径 == 当前节点.L路径 { // 不能依赖自身
			当前节点.C错误 = consts.X新建请求验证错误(fmt.Sprintf("node cannot ref self: (%s)", 引用路径))
			return
		}

		值节点 := 当前节点.C查询上下文.L路径节点映射[引用路径]
		if 值节点 == nil {
			h.J节点.C错误 = consts.X新建请求验证错误(fmt.Sprintf("param %s no found on %s", 参数键列表[i], 函数名))
			return
		}
		if 值节点.F返回值 != nil {

			switch 值节点.F返回值.(type) {
			case model.Map:
				参数[参数定义.M名称] = util.Z转字符串(值节点.F返回值.(model.Map)[参数名])
			case string:
				参数[参数定义.M名称] = 值节点.F返回值.(string)
			}

		} else {
			参数[参数定义.M名称] = util.Z转字符串(值节点.J简单请求值)
		}
	}

	当前节点.F返回值, 当前节点.C错误 = 查询配置.T调用函数(当前节点.S上下文, 函数名, 参数)
}

func (h *H函数节点) J节点类型() int {
	return J节点类型结构
}
